package com.menghao.rpc.util;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>原子整形类.<br>
 *
 * @author MarvelCode.
 */
public class AtomicPositiveInteger extends Number {

    private AtomicInteger value;
    private int max;
    private int min;

    public AtomicPositiveInteger() {
        this(0, 0, 2147483647);
    }

    public AtomicPositiveInteger(int initialValue) {
        this(initialValue, 0, 2147483647);
    }

    public AtomicPositiveInteger(int initialValue, int min, int max) {
        this.value = new AtomicInteger(initialValue);
        this.min = min;
        this.max = max;
    }

    public final int getAndIncrement() {
        int current;
        int next;
        do {
            current = value.get();
            next = current >= this.max ? this.min : current + 1;
        } while (value.compareAndSet(current, next));
        return current;
    }

    public final int getAndDecrement() {
        int current;
        int next;
        do {
            current = value.get();
            next = current <= this.min ? this.max : current - 1;
        } while (value.compareAndSet(current, next));
        return current;
    }

    public final int incrementAndGet() {
        int current;
        int next;
        do {
            current = value.get();
            next = current >= this.max ? this.min : current + 1;
        } while (!value.compareAndSet(current, next));
        return next;
    }

    public final int decrementAndGet() {
        int current;
        int next;
        do {
            current = value.get();
            next = current <= this.min ? this.max : current - 1;
        } while (!value.compareAndSet(current, next));
        return next;
    }

    @Override
    public int intValue() {
        return value.intValue();
    }

    @Override
    public long longValue() {
        return value.longValue();
    }

    @Override
    public float floatValue() {
        return value.floatValue();
    }

    @Override
    public double doubleValue() {
        return value.doubleValue();
    }
}
